﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Model.Spells;
using System.ComponentModel;
//using System.Runtime.Serialization;
//using System.Security.Permissions;

using Model.Items;
using Model.Player;
using Model.Adventure;

using RemotingInterfaces;

namespace Model.Hero
{
    [Serializable]
    public class Hero : Character, IHero
    {
        private Player.Player _owner;

        //inventory: items, pots, rare mats
        private List<Item> inventory;
        private RagDoll _ragdoll; 
        //combos
        //list of monters killed, ex. 145 orcs, 2 dragons, 3 ogres etc. (only TYPE of monster, which is not templated, but "hardcoded")
        //hvordan gør man det smartest? måske 50+ forskellige typer monstre
        private List<ISpell> _queued_spells; //spells queued for casting in the following combat round
        
        private List<Archivement> _archivements;                       
        private List<Quest> _quests;

        //party vars
        private bool _party_leader;

        //base rating for attack and defense
        private const int base_rating = 10;
        private const double _vitality_health_multiplier = 7.5;

        public Hero(String name, String race)
            : base(race)
        {            
            Name = name;
            Level = 1;
            CurrentHealth = Health;
            _ragdoll = new RagDoll();            
        }

        public Player.Player Owner
        {
            get { return _owner; }
            set
            {
                _owner = value;
            }
        }

        public RagDoll ragDoll
        {
            get { return _ragdoll; }
        }      

        public long XP
        {
            get { return _XP; }
            set
            {
                _XP = value;
                while (_XP > XPToLvl)
                {
                    _XP -= XPToLvl;
                    LevelUp();
                }                

                NotifyPropertyChanged("XP");
            }
        }

        public long XPToLvl
        {       
            //skal overvejes lidt bedre. skal balanceres fra lvl 1-99, hvor at man skal spille MEGET for at nå lvl 99
            get { return (long)(Math.Exp(3.0 * Math.Log(_level, 2.00)) * (1 - Math.Min(15, _level) * 0.02) + 1500 * _level); }
        }

        void LevelUp()
        {
            Level++;
            //+stat points, skill points            

            //full health at lvl up
            CurrentHealth = Health;
        }
        
        //top lvl att/def ratings are integers
        public int Attack_Rating
        {
            //calculated based on weapon + skills + stats + base
            get { return (int)Math.Floor(base_rating + ragDoll.Attack_Rating + 2.5 * Strength); }
        }

        public int Defense_Rating
        {
            //calculated based on armor + shield + skills + stats + base
            get { return (int)Math.Floor(base_rating + ragDoll.Defense_Rating + 2.0 * Agility); }
        }

        public void EquipItem(Item item)
        {
            _ragdoll.EquipItem(item);
            //binding to attack og defense rating
            NotifyPropertyChanged("Attack_Rating");
            NotifyPropertyChanged("Defense_Rating");
        }

        public void EuipItemInSlot(Item item, Slot slot)
        {
            _ragdoll.EquipItemInSlot(item, slot);
            //binding to attack og defense rating
            NotifyPropertyChanged("Attack_Rating");
            NotifyPropertyChanged("Defense_Rating");
        }

        public void UnequipItem(Slot slot)
        {
            _ragdoll.UnequipItem(slot);
            //binding to attack og defense rating
            NotifyPropertyChanged("Attack_Rating");
            NotifyPropertyChanged("Defense_Rating");
        }

        public int Health
        {
            get { return (int)Math.Floor(Vitality * _vitality_health_multiplier * _level); }
        }

        public int Gold
        {
            get { return _gold; }
            set
            {
                _gold = value;
                NotifyPropertyChanged("Gold");
            }
        }

        public void AwardXP(long xp)
        {
            XP += xp;
        }       

        public override String ToString()
        {
            String str =
                    base.ToString() +
                   /*"Name: " + Name + "\n" +
                   "Race: " + GetRace + "\n" +                   
                   "Level: " + Level + "\n" +
                   "Strength: " + Strength + "\n" +
                   "Intellect: " + Intellect + "\n" +
                   "Perception: " + Perception + "\n" + 
                   "Agility: " + Agility + "\n" +
                   "Vitality: " + Vitality + "\n" +
                   //*/
                   "Attack Rating: " + Attack_Rating + "\n" +
                   "Defense Rating: " + Defense_Rating + "\n" +
                   "Health: " + Health + "\n" +
                   "Current health: " + CurrentHealth + "\n" +
                   "XP: " + XP + "\n" +                   
                   "XP to next level: " + XPToLvl + "\n";    
            /*str += "Feats:\n";
            foreach (Feat f in _feats)
            {
                str += f.Name + "\n";
            }//*/
                
            return str;
        }

    }
}
